# 事务状态管理器, 使用数据库做存储单位，   api_web_hook
import  traceback
import  json

from flask import request
from tools.basic_tools import Tools
from app.models.rangeModel import WebHookJob
from tools import db
from app.common.zstack_manager import ZStackManager
from app.api.v1.webhook.webhook_manager import WebHookManager
from app.api.v1.webhook.operate_config import OPERATE
from tools import redis_publist

class TransactionContext(WebHookManager):
    def __init__(self, work_uuid=None):
        super(TransactionContext, self).__init__()
        self.work_uuid = Tools.get_uuid4_no_line() if not work_uuid else work_uuid
        self.results = {}
        self.status = 0
        self.transaction_data = {}

    def add_request_data(self, request_id, request_data):
        self.transaction_data[request_id] = request_data

    def get_request_data(self, request_id):
        return self.transaction_data.get(request_id)

    def add_store_db(self, action, range_uuid):
        # 存库
        try:
            user_only = request.headers.get("Useronly")
            for key, value in action.items():
                web_hook_job = WebHookJob(
                    work_uuid=self.work_uuid,
                    range_uuid=range_uuid,
                    job_uuid=Tools.get_uuid4_no_line(),
                    action=key.split("-")[0],
                    message_state=value.pop("state", 0),
                    faild_message=value.pop("faild_message", ""),
                    request_params=value,
                    state=0,
                    message_uuid=user_only
                )
                db.session.add(web_hook_job)
            db.session.commit()
        except Exception:
            print(traceback.print_exc())
            db.session.rollback()
        return
    
    def run_request(self, job_uuid=None, state=0, data=None):
        if data is None:
            data = {}
        try:
            # 发送请求:
            query = WebHookJob.query.filter_by(state=state)
            if job_uuid:
                query = query.filter_by(job_uuid=job_uuid)
            else:
                query = query.filter_by(work_uuid=self.work_uuid)

            web_hook = query.order_by(WebHookJob.id.asc()).first()
            func = web_hook.action
            while True:
                # 合并参数
                if func in ["create_vm", "create_vpc_router"]:
                    params = {**{"job_uuid": web_hook.job_uuid}, **web_hook.request_params}
                else:
                    params = {**{**{"job_uuid": web_hook.job_uuid}, **data}, **web_hook.request_params}
                print("params====================:", params)
                eval(f"self.{func}")(**params)
                if func.endswith("database"):
                    state = 2
                    if  web_hook.message_state == 1:
                        # 推送消息
                        message = {
                            "user_only": web_hook.message_uuid, 
                            "operate": web_hook.action,
                            "code": 0,
                            "message": f"{OPERATE[web_hook.action]}成功"
                            }
                        redis_publist("channel:1", json.dumps(message))
                    WebHookJob.query.filter_by(job_uuid=web_hook.job_uuid).update({"state": state})
                    db.session.commit()
                    # 继续执行下一个任务
                    web_hook = WebHookJob.query.filter_by(state=0, work_uuid=web_hook.work_uuid).order_by(WebHookJob.id.asc()).first()
                    if not web_hook:
                        break
                    func = web_hook.action
                else:
                    state = 1  
                    WebHookJob.query.filter_by(job_uuid=web_hook.job_uuid).update({"state": state})
                    db.session.commit()
                    break
        except Exception:
            db.session.rollback()
            print(traceback.print_exc())
        
        
    def response_or_request(self, job_uuid=None, data=None):
        # sourcery skip: extract-method
        if data is None:
            data = {}
        try:
            query = WebHookJob.query.filter_by(job_uuid=job_uuid)
            web_hook = query.first()
            if not web_hook:
                return
            work_uuid = web_hook.work_uuid
            # 更新state
            query.update({"state": 2, "result": data})
            if  web_hook.message_state == 1:
                # 推送消息
                message = {
                    "user_only": web_hook.message_uuid, 
                    "operate": web_hook.action,
                    "code": 0,
                    "message": f"{OPERATE[web_hook.action]}成功"
                    }
                redis_publist("channel:1", json.dumps(message))
            
            web_next_job = WebHookJob.query.filter_by(work_uuid=work_uuid, state=0).order_by(WebHookJob.id.asc())
            web_next_info = web_next_job.first()
            db.session.commit()
            if web_next_info:
                self.run_request(job_uuid=web_next_info.job_uuid, data=data)
        except Exception:
            db.session.rollback()
            print(traceback.print_exc())
        return
            
        
    def store_result(self, step, result):
        self.results[step] = result

    def set_status(self, status):
        self.status = status

    def rollback(self, job_uuid, error):
        # 根据记录的失败步骤和事务ID执行回滚操作
        # 推送消息
        try:
            query = WebHookJob.query.filter_by(job_uuid=job_uuid)
            web_hook = query.first()
            work_uuid = web_hook.work_uuid
            # 更新state
            query.update({"state": 3, "result": error})
            if web_hook.faild_message:
                message = {**web_hook.faild_message, "code": 1, "user_only": web_hook.message_uuid}
            else:
                message = {
                    "user_only": web_hook.message_uuid, 
                    "operate": web_hook.action,
                    "code": 1,
                    "message": f"{OPERATE[web_hook.action]}失败"
                    }
            redis_publist("channel:1", json.dumps(message))
        except Exception:
            db.session.rollback()

def create_transaction(action_params, range_uuid):
    """
    action_params = {
        "func1": {
            xx: xx
        },
        "func2": {
            "xx":"xx"
        }
    }
    """
    transaction = TransactionContext()
    # 初始化事务

    # 检查事务状态并根据需要执行其他操作
    if transaction.status == 0:
        print("事务执行成功")
        transaction.add_store_db(action_params, range_uuid)
        transaction.run_request(state=0)
        # 继续处理其他逻辑
    elif transaction.status == "failed":
        print("事务执行失败，进行回滚")
        # 处理回滚后的逻辑


    

    
